#include <mutex>
#include <thread>
#include <memory>

#ifdef WIN32
#include <sys/timeb.h>
#include <time.h>
#else
#include <sys/time.h>
#endif

#include "evutil.h"

#include "SLT_logImpl.h"
#include "SLT_log.h"

static const char* const LOG_STRING[] =
{
	"T",
	"D",
	"I",
	"W",
	"E",
	"F",
};

static CLogHelper   *g_pInstance_20200309 = nullptr;
static CLogHelper* getLoggerInst()
{
	if (g_pInstance_20200309 == NULL) {
		g_pInstance_20200309 = new CLogHelper();
	}
	return g_pInstance_20200309;
}

int SLT_logInit()
{ 
	return getLoggerInst()->init();
}
void	SLT_logUninit()
{
	getLoggerInst()->uninit();
}
void  SLT_setLogConfig(const char* _configFile)
{
	if(nullptr == _configFile){
		getLoggerInst()->config(std::string(),false);
		//getLoggerInst()->config({},false);
		return ;
	}
	getLoggerInst()->config(_configFile,false);
}
void  SLT_enableConfig(bool _bconfig)
{
	getLoggerInst()->m_bconfig = _bconfig;
}

//*****修改配置文件参数*****

void  SLT_setLogPath(const char* _logpath)
{
	getLoggerInst()->setLogPath(_logpath);
}
void  SLT_setLogLevel(int _id,int _level)
{
	getLoggerInst()->setLogLevel(_id,_level);
}
void  SLT_setLogDisplay(int _id, int _disp)
{
	getLoggerInst()->setLogDisplay(_id,_disp);
}
void  SLT_setLogDisplaySync(int _id, int _sync)
{
	getLoggerInst()->setLogDisplaySync(_id,_sync);
}




bool SLT_checkLogShow(int _id, int _level) 
{
	if (! g_pInstance_20200309 || g_pInstance_20200309->m_loggers[_id]._level > _level) {
		return false;
	}
	return true;
}
void SLT_WriteLog(int _id, int _level, const char* _pfile, int _fileline, const char* _mesg, ...)
{
	if (! g_pInstance_20200309->m_init) {
		return;
	}
	//char _log_[1024];
#define _slt_log_buf_len 2048
	CLogHelper::loggerhead* _ploghead_ = (CLogHelper::loggerhead*)new char[_slt_log_buf_len + sizeof(CLogHelper::loggerhead)];
	if(!_ploghead_){
		return;
	}

	int i, j;

	struct tm _log_t2;
	struct timeval _log_tv;
	struct tm* _log_t = &_log_t2;
	evutil_gettimeofday(&_log_tv, nullptr);
	
#ifdef WIN32
	time_t ltime_ = _log_tv.tv_sec;
	localtime_s(_log_t ,&ltime_);
#else
	//_log_t = localtime(&_log_tv.tv_sec);
	localtime_r(&_log_tv.tv_sec, _log_t);
#endif
	
	std::ostringstream _log_oss;
	_log_oss << std::this_thread::get_id();

	const char* pNameEnd = _pfile + strlen(_pfile);
	const char* pNameBegin = pNameEnd;
	do
	{
		if (*pNameBegin == '\\' || *pNameBegin == '/') { pNameBegin++; break; }
		if (pNameBegin == _pfile) { break; }
		pNameBegin--;
	} while (true);
	const char* pName = pNameBegin;

	i = snprintf(_ploghead_->_data, _slt_log_buf_len,"%d%02d%02d %02d:%02d:%02d.%03ld +%s+%d[%s]%s:%d ",
		1900 + _log_t->tm_year, 1 + _log_t->tm_mon, _log_t->tm_mday, _log_t->tm_hour, _log_t->tm_min, _log_t->tm_sec, _log_tv.tv_usec / 1000,
		LOG_STRING[_level], _id,_log_oss.str().c_str(), pName, _fileline);

	va_list va;
	va_start(va, _mesg);
	j = vsnprintf((char*)_ploghead_->_data + i, _slt_log_buf_len - i, _mesg, va);
//#ifdef WIN32
//	j = vsnprintf((char*)_ploghead_->_data + i, _slt_log_buf_len -i, _mesg, va);
//#else
//	//j = vsprintf(_logPtr_.get() + i, mesg, va) + i;
//	j = vsnprintf(_logPtr_ + i, _slt_log_buf_len - i, mesg, va);
//#endif
	va_end(va);

	if (j < _slt_log_buf_len - i) {
		j = j + i;
	}
	else if (j >= _slt_log_buf_len - i) {
		j = _slt_log_buf_len -1;
		_ploghead_->_data[_slt_log_buf_len - 2] = '\n';
		_ploghead_->_data[_slt_log_buf_len - 1] = 0;
	}
	else {
		printf("\nlog vsnprintf error\n");
		return;
	}

	LoggerInfo* ploggerinfo = &g_pInstance_20200309->m_loggers[_id];
	if (ploggerinfo->_display){
		if (ploggerinfo->_sync_display_out) {
			printf("%s", _ploghead_->_data);
			_ploghead_->_disp = false;
		}
		else {
			_ploghead_->_disp = true;
		}
	}
	else {
		_ploghead_->_disp = false;
	}

	//printf("%s", _logPtr_.get());
	_ploghead_->_len = j;
	g_pInstance_20200309->writeLog(_ploghead_);
}


